package com.zoe.onelink.core.web.jackson.serializer;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
import com.fasterxml.jackson.databind.node.IntNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.zoe.onelink.common.enumeration.BaseEnum;
import com.zoe.onelink.common.enumeration.ExceptionCodeEnum;
import com.zoe.onelink.common.exception.ApiException;
import lombok.NonNull;

import java.io.IOException;
import java.io.Serializable;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2021</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2021-04-22
 */
public class JacksonEnumSimpleDeserializers extends SimpleDeserializers {


    @Override
    public JsonDeserializer<?> findEnumDeserializer(Class<?> type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException {
        if (BaseEnum.class.isAssignableFrom(type)) {
            Class<BaseEnum<Serializable>> baseEnum = (Class<BaseEnum<Serializable>>) type;
            return new CustomEnumDeserializer(baseEnum);
        }
        return super.findEnumDeserializer(type, config, beanDesc);
    }

    public static class CustomEnumDeserializer extends JsonDeserializer<BaseEnum<Serializable>> {

        protected final Class<BaseEnum<Serializable>> enumClass;

        public CustomEnumDeserializer(@NonNull Class<BaseEnum<Serializable>> enumClass) {
            this.enumClass = enumClass;
        }

        @Override
        public BaseEnum<Serializable> deserialize(JsonParser parser, DeserializationContext ctx) throws IOException {
            TreeNode node = parser.readValueAsTree();
            Serializable nodeVal;

            // 数字类型节点
            Class<? extends TreeNode> nodeClass = node.getClass();
            if (nodeClass == IntNode.class) {
                nodeVal = ((IntNode) node).intValue();
                // 字符串节点
            } else if (nodeClass == TextNode.class) {
                nodeVal = ((TextNode) node).asText();
                // JSON对象类型节点
            } else if (nodeClass == ObjectNode.class) {
                JsonNode codeNode = ((ObjectNode) node).get("code");
                nodeVal = codeNode == null ? null : codeNode.asText();
            } else {
                throw ApiException.createEx(ExceptionCodeEnum.REQ_ARG_ENUM_DESERIALIZATION_FAILURE, this.enumClass.getSimpleName());
            }
            return BaseEnum.getByCode(this.enumClass, nodeVal);
        }

        @Override
        public Class<BaseEnum<Serializable>> handledType() {
            return this.enumClass;
        }

    }
}
